package com.devops.admin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devops.admin.mapper.DOSApplyYamlMapper;
import com.devops.admin.model.*;
import com.devops.admin.service.*;
import com.devops.admin.util.Assert;
import com.devops.admin.util.K8sClientUtil;
import com.devops.admin.vo.DOSApplyYamlVo;
import com.devops.common.utils.Message;
import com.devops.constant.DevOpsConstant;
import com.devops.shiro.vm.BaseUserVM;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.extensions.Ingress;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.Yaml;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName DOSApplyYamlServiceImpl
 * @Description TODO
 * @Author hepingguo
 * @Date 2022/7/14 16:17
 * @Version 1.0
 **/
@Service
public class DOSApplyYamlServiceImpl extends ServiceImpl<DOSApplyYamlMapper, DOSApplyYaml> implements DOSApplyYamlService {

    @Autowired
    private DOSReleaseService dosReleaseService;
    @Autowired
    private DOSClusterNamespaceService dosClusterNamespaceService;
    @Autowired
    private DOSClusterInfoService dosClusterInfoService;
    @Autowired
    private DOSEnvClusterRelationService dosEnvClusterRelationService;
    @Autowired
    DOSReleaseOperateLogService dosReleaseOperateLogService;

    @Override
    public Message applyByYaml(DOSApplyYamlVo applyYaml) {
        Assert.isTrue(applyYaml.getClusterId() != null && applyYaml.getClusterId() > 0, "集群id不能为空");
        Assert.isTrue(applyYaml.getNamespaceId() != null && applyYaml.getNamespaceId() > 0, "命名空间Id不能为空");
        Assert.isTrue(applyYaml.getProjectId() != null && applyYaml.getClusterId().intValue() > 0, "项目id不能为空");
        Assert.isTrue(StrUtil.isNotBlank(applyYaml.getValues()), "yaml文件内容不能为空");

        try {
            // 解析yaml
            Map<String, Object> map = getDeployment(applyYaml.getValues());
            Map<String,String> labelMap = (Map<String, String>) map.get("labelMap");
            String namespaces = null;
            if (map.get("namespace") != null){
                namespaces = map.get("namespace").toString();
            }else if (map.get("serviceNamespace") != null){
                namespaces = map.get("serviceNamespace").toString();
            }else if (map.get("ingressNamespace") != null){
                namespaces = map.get("ingressNamespace").toString();
            }

            // 获取命名空间,然后校验命名空间是否已经绑定该项目
            DOSClusterNamespace namespace = dosClusterNamespaceService.getById(applyYaml.getNamespaceId());

            // 获取集群的ConfigContent
            LambdaQueryWrapper<DOSClusterInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DOSClusterInfo::getClusterId, applyYaml.getClusterId());
            List<DOSClusterInfo> clusterInfos = dosClusterInfoService.list(queryWrapper);
            Assert.isTrue(CollectionUtil.isNotEmpty(clusterInfos), "请检查集群id是否合法");
            Assert.isTrue(clusterInfos.size() == 1,"查询集群的ConfigContent数据出错");

            // 查询环境类型
            LambdaQueryWrapper<DOSEnvClusterRelation> relationQueryWrapper = new LambdaQueryWrapper<>();
            relationQueryWrapper.eq(DOSEnvClusterRelation::getClusterId, applyYaml.getClusterId());
            List<DOSEnvClusterRelation> envTypes = dosEnvClusterRelationService.list(relationQueryWrapper);
            Assert.isTrue(CollectionUtil.isNotEmpty(envTypes), "未查询到集群的环境信息");

            // 根据yaml文件部署项目
            InputStream inputStream = new ByteArrayInputStream(applyYaml.getValues().getBytes(StandardCharsets.UTF_8));
            KubernetesClient client = K8sClientUtil.getKubernetesClient(clusterInfos.get(0).getConfigPath(), clusterInfos.get(0).getConfigContent());
            Assert.isTrue(checkDeployment(client,map),"已存在相同的deployment，无法重新部署");
            Assert.isTrue(checkService(client,map),"已存在相同的Service，无法重新部署");
            Assert.isTrue(checkIngress(client,map),"已存在相同的Ingress，无法重新部署");
            List<HasMetadata> results = client.load(inputStream).inNamespace(namespace.getNamespace()).createOrReplace();

            // 部署失败直接返回false
            if (CollectionUtil.isEmpty(results)) {
                // 添加操作失败日志
                setLog(applyYaml, 0, "操作失败",DevOpsConstant.ReleaseOperationFlag.INSTALL);
                return Message.error("操作失败：");
            }

            Deployment deployment;
            io.fabric8.kubernetes.api.model.Service service;
            Ingress ingress;
            for (HasMetadata hasMetadata : results) {
                // 如果为Deployment则取出reversion
                if (hasMetadata instanceof Deployment){
                    deployment = (Deployment) hasMetadata;
                }
                // 如果为service
                if (hasMetadata instanceof io.fabric8.kubernetes.api.model.Service){
                    service = (io.fabric8.kubernetes.api.model.Service) hasMetadata;
                }
                // 如果为ingress
                if (hasMetadata instanceof Ingress){
                    ingress = (Ingress) hasMetadata;
                }
            }



            DOSRelease release = null;
            if (applyYaml.getReleaseId() != null && applyYaml.getReleaseId() > 0){
                release = dosReleaseService.getById(applyYaml.getReleaseId());
            }

            //根据集群id和namespace获取命名空间id
            LambdaQueryWrapper<DOSClusterNamespace> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(DOSClusterNamespace::getClusterId,applyYaml.getClusterId())
                    .eq(DOSClusterNamespace::getNamespace,namespaces);
            DOSClusterNamespace clusterNamespace = dosClusterNamespaceService.getOne(queryWrapper1);
            applyYaml.setNamespaceId(clusterNamespace.getId());

            // 组装applyYaml文件并入库
            // 获取matichLabels并转换为json
            JSONObject labels = null;
            if (CollectionUtil.isNotEmpty(labelMap)) {
                labels = JSONUtil.parseObj(labelMap);
            }
            DOSApplyYaml dosApplyYaml = DOSApplyYaml.builder()
                    .yamlValue(applyYaml.getValues())
                    .labels(labels!=null ? labels.toString() : null)
                    .build();
            if (release != null){
                dosApplyYaml.setId(release.getApplyYamlId());
                this.updateById(dosApplyYaml);
            }else {
                // 保存或更新yaml
                this.save(dosApplyYaml);
            }

            // 组装release并落库
            DOSRelease dosRelease = saveRelease(applyYaml, envTypes, dosApplyYaml);

            // 添加操作成功日志
            setLog(applyYaml, dosRelease.getId(), "操作成功",DevOpsConstant.ReleaseOperationFlag.INSTALL);
        } catch (Exception e) {
            e.printStackTrace();
            // 添加操作失败日志
            setLog(applyYaml, 0, "操作失败"+e.getMessage(),DevOpsConstant.ReleaseOperationFlag.INSTALL);
            return Message.error("操作失败："+e.getMessage());
        }
        return Message.ok("操作成功");
    }

    /**
     * @Author heyabo
     * @Description 保存release
     * @Date 10:27 2022/7/19
     * @Param [applyYaml, deployment, envTypes, dosApplyYaml]
     * @return com.devops.admin.model.DOSRelease
     **/
    private DOSRelease saveRelease(DOSApplyYamlVo applyYaml, List<DOSEnvClusterRelation> envTypes, DOSApplyYaml dosApplyYaml) {
        DOSRelease dosRelease = DOSRelease.builder()
                .releaseName(applyYaml.getReleaseName())
                .applyYamlId(dosApplyYaml.getId())
                .releaseType(DevOpsConstant.ReleaseType.YAML)
                .clusterId(applyYaml.getClusterId())
                .namespaceId(applyYaml.getNamespaceId())
                .projectId(applyYaml.getProjectId())
                .envType(envTypes.get(0).getEnvType())
                .build();

        // 根据查询结果更新或者保存release
        if (applyYaml.getReleaseId() != null && applyYaml.getReleaseId() > 0){
            DOSRelease release = dosReleaseService.getById(applyYaml.getReleaseId());
            if (release == null) {
                dosReleaseService.save(dosRelease);
            }else {
                dosRelease.setId(applyYaml.getReleaseId());
                dosReleaseService.updateById(dosRelease);
            }
        }else {
            dosReleaseService.save(dosRelease);
        }
        return dosRelease;
    }

    @Override
    public DOSApplyYaml getLabels(Integer releaseId) {
        return baseMapper.getLabels(releaseId);
    }

    @Override
    public Message rollBackHistory(DOSApplyYamlVo applyYaml) {
        Assert.isTrue(applyYaml.getReleaseId() != null && applyYaml.getReleaseId() > 0,"releaseId不能为空");
        try {
            DOSRelease release = dosReleaseService.getById(applyYaml.getReleaseId());

            Assert.isTrue(release != null,"请检查releaseId是否合法");

            // 获取命名空间,然后校验命名空间是否已经绑定该项目
            DOSClusterNamespace namespace = dosClusterNamespaceService.getById(release.getNamespaceId());
            Assert.isTrue(namespace != null, "请检查命名空间id是否合法");

            // 获取集群的ConfigContent
            LambdaQueryWrapper<DOSClusterInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DOSClusterInfo::getClusterId, release.getClusterId());
            List<DOSClusterInfo> clusterInfos = dosClusterInfoService.getBaseMapper().selectList(queryWrapper);
            Assert.isTrue(CollectionUtil.isNotEmpty(clusterInfos), "请检查集群id是否合法");
            Assert.isTrue(clusterInfos.size() == 1,"集群详细信息出错");

            // 查询环境类型
            LambdaQueryWrapper<DOSEnvClusterRelation> relationQueryWrapper = new LambdaQueryWrapper<>();
            relationQueryWrapper.eq(DOSEnvClusterRelation::getClusterId, release.getClusterId());
            List<DOSEnvClusterRelation> envTypes = dosEnvClusterRelationService.list(relationQueryWrapper);
            Assert.isTrue(CollectionUtil.isNotEmpty(envTypes), "未查询到集群的环境信息");

            // 根据yaml文件部署项目
            KubernetesClient client = K8sClientUtil.getKubernetesClient(clusterInfos.get(0).getConfigPath(), clusterInfos.get(0).getConfigContent());
            client.apps().deployments().inNamespace(namespace.getNamespace()).withName(release.getReleaseName())
                    .rolling()
                    .undo();
            // 添加release回滚日志
            setLog(applyYaml,applyYaml.getReleaseId(),"操作成功",DevOpsConstant.ReleaseOperationFlag.ROLLBACK);
        }catch (Exception e){
            // 回滚失败日志
            setLog(applyYaml,applyYaml.getReleaseId(),"操作失败:"+e.getMessage(),DevOpsConstant.ReleaseOperationFlag.ROLLBACK);
            e.printStackTrace();
            return Message.error("操作失败："+e.getMessage());

        }
        return Message.ok("回滚成功");
    }

    @Override
    public Message deleteByYaml(DOSApplyYamlVo applyYaml) {
        Assert.isTrue(applyYaml.getReleaseId() != null && applyYaml.getReleaseId() > 0,"releaseId不能为空");
        DOSApplyYaml dosApplyYaml = baseMapper.getLabels(applyYaml.getReleaseId());
        Assert.isTrue(dosApplyYaml != null,"未查询到yaml文件相关信息");
        applyYaml.setValues(dosApplyYaml.getYamlValue());

        // 获取release相关信息
        DOSRelease release = dosReleaseService.getById(applyYaml.getReleaseId());
        Assert.isTrue(release != null,"releaseId不合法");


        //获取命名空间信息
        DOSClusterNamespace namespace = dosClusterNamespaceService.getById(release.getNamespaceId());
        Assert.isTrue(namespace != null,"未查询到namespace信息");

        // 获取集群的ConfigContent
        LambdaQueryWrapper<DOSClusterInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DOSClusterInfo::getClusterId, release.getClusterId());
        List<DOSClusterInfo> clusterInfos = dosClusterInfoService.list(queryWrapper);
        Assert.isTrue(CollectionUtil.isNotEmpty(clusterInfos), "请检查集群id是否合法");
        Assert.isTrue(clusterInfos.size() == 1,"查询集群ConfigContent数据出错");

        KubernetesClient client = K8sClientUtil.getKubernetesClient(clusterInfos.get(0).getConfigPath(), clusterInfos.get(0).getConfigContent());

        // 根据yaml文件部署项目
        InputStream inputStream = new ByteArrayInputStream(applyYaml.getValues().getBytes(StandardCharsets.UTF_8));
        boolean isDelete = false;
        try{
            // 卸载deployment的核心代码
            isDelete = !client.load(inputStream)
                    .inNamespace(namespace.getNamespace())
                    .delete()
                    .isEmpty();
        }catch (Exception e){
            // 设置卸载失败日志
            setLog(applyYaml,applyYaml.getReleaseId(),"卸载失败",DevOpsConstant.ReleaseOperationFlag.UNINSTALL);
            e.printStackTrace();
        }

        if (isDelete){
            // 设置卸载成功日志
            setLog(applyYaml,applyYaml.getReleaseId(),"卸载成功",DevOpsConstant.ReleaseOperationFlag.UNINSTALL);
            // 删除相关的release 和 yaml文件
            dosReleaseService.removeById(applyYaml.getReleaseId());
            this.removeById(dosApplyYaml.getId());
            return Message.ok("卸载成功");
        }
        // 设置卸载失败日志
        setLog(applyYaml,applyYaml.getReleaseId(),"卸载失败",DevOpsConstant.ReleaseOperationFlag.UNINSTALL);
        return Message.error("卸载失败");
    }

    @Override
    public Message upgradeByYaml(DOSApplyYamlVo applyYaml) {
        Assert.isTrue(applyYaml.getReleaseId() != null && applyYaml.getReleaseId() > 0, "集群id不能为空");
        Assert.isTrue(StrUtil.isNotBlank(applyYaml.getValues()), "yaml文件内容不能为空");

        DOSRelease release = dosReleaseService.getById(applyYaml.getReleaseId());
        Assert.isTrue(ObjectUtil.isNotEmpty(release),"releaseId不合法");

        try {
            // 解析yaml
            Map<String, Object> map = getDeployment(applyYaml.getValues());
            Map<String,String> labelMap = (Map<String, String>) map.get("labelMap");
            String namespaces = null;
            if (map.get("namespace") != null){
                namespaces = map.get("namespace").toString();
            }else if (map.get("serviceNamespace") != null){
                namespaces = map.get("serviceNamespace").toString();
            }else if (map.get("ingressNamespace") != null){
                namespaces = map.get("ingressNamespace").toString();
            }

            DOSApplyYaml applyYamlPo = this.getById(release.getApplyYamlId());
            Assert.isTrue(applyYaml!=null,"请检查releaseId是否合法");
            // 校验升级前后的yaml关键信息是否被篡改，如果被篡改不能被升级
            checkYaml(applyYamlPo.getYamlValue(),map);

            // 获取命名空间,然后校验命名空间是否已经绑定该项目
            DOSClusterNamespace namespace = dosClusterNamespaceService.getById(release.getNamespaceId());

            // 获取集群的ConfigContent
            LambdaQueryWrapper<DOSClusterInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DOSClusterInfo::getClusterId, release.getClusterId());
            List<DOSClusterInfo> clusterInfos = dosClusterInfoService.list(queryWrapper);
            Assert.isTrue(CollectionUtil.isNotEmpty(clusterInfos), "请检查集群id是否合法");
            Assert.isTrue(clusterInfos.size() == 1,"查询集群的ConfigContent数据出错");

            // 查询环境类型
            LambdaQueryWrapper<DOSEnvClusterRelation> relationQueryWrapper = new LambdaQueryWrapper<>();
            relationQueryWrapper.eq(DOSEnvClusterRelation::getClusterId, release.getClusterId());
            List<DOSEnvClusterRelation> envTypes = dosEnvClusterRelationService.list(relationQueryWrapper);
            Assert.isTrue(CollectionUtil.isNotEmpty(envTypes), "未查询到集群的环境信息");

            // 根据yaml文件部署项目
            InputStream inputStream = new ByteArrayInputStream(applyYaml.getValues().getBytes(StandardCharsets.UTF_8));
            KubernetesClient client = K8sClientUtil.getKubernetesClient(clusterInfos.get(0).getConfigPath(), clusterInfos.get(0).getConfigContent());
            List<HasMetadata> results = client.load(inputStream).inNamespace(namespace.getNamespace()).createOrReplace();

            // 部署失败直接返回false
            if (CollectionUtil.isEmpty(results)) {
                // 添加操作失败日志
                setLog(applyYaml, 0, "操作失败",DevOpsConstant.ReleaseOperationFlag.INSTALL);
                return Message.error("操作失败：");
            }

            //TODO 这里先取出项目部署的reversion，暂时不入库，等后续情况再决定是否入库
            int reversion = 0;
            for (HasMetadata hasMetadata : results) {
                // 如果为Deployment则取出reversion
                if (hasMetadata instanceof Deployment){
                    reversion = Math.toIntExact(hasMetadata.getMetadata().getGeneration());
                }
            }

            //根据集群id和namespace获取命名空间id
            LambdaQueryWrapper<DOSClusterNamespace> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(DOSClusterNamespace::getClusterId,release.getClusterId())
                    .eq(DOSClusterNamespace::getNamespace,namespaces);
            DOSClusterNamespace clusterNamespace = dosClusterNamespaceService.getOne(queryWrapper1);
            applyYaml.setNamespaceId(clusterNamespace.getId());

            // 组装applyYaml文件并入库
            // 获取matichLabels并转换为json
            JSONObject labels = null;
            if (CollectionUtil.isNotEmpty(labelMap)) {
                labels = JSONUtil.parseObj(labelMap);
            }
            DOSApplyYaml dosApplyYaml = DOSApplyYaml.builder()
                    .yamlValue(applyYaml.getValues())
                    .labels(labels != null ? labels.toString() : null)
                    .build();
            if (release != null){
                dosApplyYaml.setId(release.getApplyYamlId());
                this.updateById(dosApplyYaml);
            }else {
                // 保存或更新yaml
                this.save(dosApplyYaml);
            }

            // 组装release并落库
            DOSRelease dosRelease = saveRelease(applyYaml, envTypes, dosApplyYaml);

            // 添加操作成功日志
            setLog(applyYaml, dosRelease.getId(), "操作成功",DevOpsConstant.ReleaseOperationFlag.INSTALL);
        } catch (Exception e) {
            e.printStackTrace();
            // 添加操作失败日志
            setLog(applyYaml, 0, "操作失败"+e.getMessage(),DevOpsConstant.ReleaseOperationFlag.INSTALL);
            return Message.error("操作失败："+e.getMessage());
        }
        return Message.ok("操作成功");
    }

    /**
     * @Author heyabo
     * @Description 设置操作日志
     * @Date 09:46 2022/7/15
     * @Param [applyYaml, dosRelease]
     * @return void
     **/
    private void setLog(DOSApplyYamlVo applyYaml, Integer releaseId,String result,Integer operationType) {
        //获取登录的用户信息 操作日志封装
        BaseUserVM user = (BaseUserVM) SecurityUtils.getSubject().getPrincipal();
        DOSReleaseOperateLog operateLog = DOSReleaseOperateLog.builder()
                .operateType(operationType)
                .operateResult(result)
                .operateValues(applyYaml.getValues())
                .releaseId(releaseId)
                .operateUserId(user.getId())
                .build();
        dosReleaseOperateLogService.save(operateLog);
    }


    /**
     * @Author heyabo
     * @Description 解析yaml文件
     * @Date 16:10 2022/8/10
     * @Param [yaml]
     * @return java.util.Map<java.lang.String,java.lang.Object>
     **/
    private Map<String, Object> getDeployment(String yaml) {
        Map<String, String> labelMap;
        Map<String, Object> map = new HashMap<>(16);
        String[] yamls = yaml.split("---");
        // 将yaml文件拆分成多份
        Yaml yamlLoad = new Yaml();
        for (String value : yamls) {
            Map<String,Object> load = yamlLoad.load(value);
            Map<String,Object> metadata = (Map<String, Object>) load.get("metadata");
            map.put("labelMap",null);
            String kind = load.get("kind").toString();
            if (kind.equals("Deployment")){
                Map<String,Object> spec = (Map<String, Object>) load.get("spec");
                Map<String,Object> selector = (Map<String, Object>) spec.get("selector");
                labelMap = (Map<String, String>) selector.get("matchLabels");
                map.put("labelMap",labelMap);
                String name = (String) metadata.get("name");
                map.put("deployment",name);
                String namespace = metadata.get("namespace").toString();
                map.put("namespace",namespace);
            }else if (kind.equals("Service")){
                Map<String,Object> spec = (Map<String, Object>) load.get("spec");
                labelMap = (Map<String, String>) spec.get("selector");
                map.put("labelMap",labelMap);
                String name = (String) metadata.get("name");
                map.put("service",name);
                String namespace = metadata.get("namespace").toString();
                map.put("serviceNamespace",namespace);
            }else if (kind.equals("Ingress")){
                String name = (String) metadata.get("name");
                map.put("ingress",name);
                String namespace = metadata.get("namespace").toString();
                map.put("ingressNamespace",namespace);
            }
        }
        return map;
    }

    /**
     * @Author heyabo
     * @Description 校验deployment是否重复安装
     * @Date 10:47 2022/8/10
     * @Param [dosClusterInfo, map]
     * @return boolean
     **/
    private boolean checkDeployment(KubernetesClient client,Map<String, Object> map){
        String namespace = map.get("namespace").toString();
        Deployment deployment = new Deployment();
        if (map.get("deployment") != null){
            String deploymentName = map.get("deployment").toString();
            deployment = client.apps().deployments().inNamespace(namespace)
                    .withName(deploymentName).get();
        }

        return deployment == null || deployment.getMetadata() == null;
    }

    /**
     * @Author heyabo
     * @Description 校验service
     * @Date 10:49 2022/8/10
     * @Param [dosClusterInfo, map]
     * @return boolean
     **/
    private boolean checkService(KubernetesClient client,Map<String, Object> map){
        String namespace = map.get("namespace").toString();
        io.fabric8.kubernetes.api.model.Service service = new io.fabric8.kubernetes.api.model.Service();
        if (map.get("service") != null){
            String serviceName = map.get("service").toString();

            service = client.services().inNamespace(namespace).withName(serviceName).get();
        }

        return service == null || service.getMetadata() == null;
    }

    /**
     * @Author heyabo
     * @Description 校验ingress
     * @Date 10:49 2022/8/10
     * @Param [dosClusterInfo, map]
     * @return boolean
     **/
    private boolean checkIngress(KubernetesClient client,Map<String, Object> map){
        String namespace = map.get("namespace").toString();
        io.fabric8.kubernetes.api.model.networking.v1.Ingress ingress = new io.fabric8.kubernetes.api.model.networking.v1.Ingress();
        if (map.get("ingress") != null){
            String ingressName = map.get("ingress").toString();
            ingress = client.network().v1().ingresses().inNamespace(namespace).withName(ingressName).get();
        }

        return ingress == null || ingress.getMetadata() == null;
    }

    /**
     * @Author heyabo
     * @Description 校验升级项目关键信息是否被篡改
     * @Date 14:57 2022/8/10
     * @Param [yamlValue, oldMap]
     * @return void
     **/
    private void checkYaml(String yamlValue,Map<String,Object> newMap){
        Map<String, Object> oldMap = getDeployment(yamlValue);
        String oldNamespace = oldMap.get("namespace") != null ? oldMap.get("namespace").toString() : "";
        String oldDeployment = oldMap.get("deployment") != null ? oldMap.get("deployment").toString() : "";
        String oldService = oldMap.get("service") != null ? oldMap.get("service").toString() : "";
        String oldIngress = oldMap.get("ingress") != null ? oldMap.get("ingress").toString() : "";
        String newNamespace = newMap.get("namespace") != null ? newMap.get("namespace").toString() : "";
        String newDeployment = newMap.get("deployment") != null ? newMap.get("deployment").toString() : "";
        String newService = newMap.get("service") != null ? newMap.get("service").toString() : "";
        String newIngress = newMap.get("ingress") != null ? newMap.get("ingress").toString() : "";
        String newIngressNamespace = newMap.get("ingressNamespace") != null ? newMap.get("ingressNamespace").toString() : "";
        String oldIngressNamespace = oldMap.get("ingressNamespace") != null ? oldMap.get("ingressNamespace").toString() : "";
        String newServiceNamespace = newMap.get("serviceNamespace") != null ? newMap.get("serviceNamespace").toString() : "";
        String oldServiceNamespace = oldMap.get("serviceNamespace") != null ? oldMap.get("serviceNamespace").toString() : "";

        if (oldDeployment.equals("") && !oldDeployment.equals(newDeployment)){
            Assert.isTrue(false,"不允许增加deployment部分yaml");
        }
        if (oldService.equals("") && !oldService.equals(newService)){
            Assert.isTrue(false,"不允许增加Service部分yaml");
        }
        if (oldIngress.equals("") && !oldIngress.equals(newIngress)){
            Assert.isTrue(false,"不允许增加ingress部分yaml");
        }

        if (!oldDeployment.equals("") && newDeployment.equals("")){
            Assert.isTrue(false,"不允许减少deployment部分yaml");
        }
        if (!oldService.equals("") && newService.equals("")){
            Assert.isTrue(false,"不允许减少Service部分yaml");
        }
        if (!oldIngress.equals("") && newIngress.equals("")){
            Assert.isTrue(false,"不允许减少ingress部分yaml");
        }

        Assert.isTrue(oldNamespace.equals(newNamespace),"deployment命名空间升级前后不一致");
        Assert.isTrue(oldDeployment.equals(newDeployment),"deployment名字升级前后不一致");
        Assert.isTrue(oldService.equals(newService),"service升级前后不一致");
        Assert.isTrue(oldIngress.equals(newIngress),"ingress升级前后不一致");
        Assert.isTrue(oldServiceNamespace.equals(newServiceNamespace),"service命名空间升级前后不一致");
        Assert.isTrue(oldIngressNamespace.equals(newIngressNamespace),"ingress命名空间升级前后不一致");
    }
}
